home *** CD-ROM | disk | FTP | other *** search
/ The Mac Mega CD - Killer Software / The Mac Mega CD - Killer Software (May 1996).dmg / Shareware City / Utilities / Digester / sources / digester.c next >
Encoding:
C/C++ Source or Header  |  1996-01-15  |  39.3 KB  |  1,811 lines  |  [TEXT/EDIT]

  1. /*     file: digester2.1b.c
  2.         purpose:    digest e-mails from info-mac digest into HTML format
  3.         author:        Andre' C. van der Ham
  4.         e-mail:        A.C.vanderHam@ET.TUDelft.NL
  5.     
  6.         notice:        Don't forget to set the path to your scripts directory
  7.             
  8.         for THINK C users:
  9.         project profile:
  10.             segment 1:     digester
  11.                         MacTraps
  12.             segment 2:    ANSI
  13.                         unix
  14.                         
  15.         project type:    size:     100K
  16.                         flags:    0080    32-bit compatibility
  17.                             
  18.         You had better also delete all the num_args and arg_strings stuff in main.
  19.         So, 'int main( void )'.
  20.         
  21. */
  22.  
  23. /* includes */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #ifdef __THINK__
  29. #include <Files.h>
  30. #include <console.h>
  31. #include <StandardFile.h>
  32. #endif
  33.  
  34. #define    LINELENGTH    80
  35. #define    DRE            "http://dutera.et.tudelft.nl/people/vdham/vdham.html"
  36. #define    PARMS        "digester.par"
  37. #define    notify        printf
  38.  
  39. int    debug=0;
  40.  
  41. FILE    *outTPrg, *outTMes, *outPrg, *outMes, *inP;
  42.  
  43. typedef struct Pars
  44. {
  45.     char    scriptPath[80];        /* path to mail script */
  46.     char    sitesFile[20];        /* path to sites file */
  47.     char    destPath[80];        /* additional path for destination files */
  48.     char    Ftype[10];            /* finder type */
  49.     char    Fcreator[10];        /* finder creator */
  50.     
  51.     char    DigestName[20];        /* name of the original digest file */
  52.     char    nameAll[20];        /* name of the complete HTML digest file */
  53.     char    nameTOC[20];        /* name of the toc only file */
  54.     char    nameProg[20];        /* name of the programs file (either with or without toc) */
  55.     char    nameMess[20];        /* name of the messages file (either with or without toc) */
  56.     
  57.     char    BegOfDigest[80];    /* begin of digest text */
  58.     char    Volume[80];            /* volume number prefix */
  59.     char    Issue[80];            /* issue number prefix */
  60.     char    Date[20];            /* date text prefix */
  61.     
  62.     char    EndOfDigest[80];    /* end of digest text */
  63.     char    BeginOfTopics[80];    /* begin of topics text */
  64.     char    EndOfTopics[80];    /* end of topics text */
  65.     char    EndOfMessage[80];    /* end of message text */
  66.     
  67.     char    RootPath[20];        /* begin of root directory of mirror */
  68.     char    BegOfFile[40];        /* begin of file path */
  69.     char    EndOfFile[20];        /* end of file path */
  70.     
  71.     int        Type;                /* type of digest */
  72.     int        Buttons;            /* buttons on/off */
  73.     int        Mail;                /* mail button on/off */
  74.     int        Files;                /* archive files link on/off */
  75.     int        URLs;                /* URL link on/off */
  76.     int        MURLs;                /* mail URLs on/off */
  77.  
  78.     char    *sites;                /* pointer to array of strings of mirror sites */
  79.     int        nSites;                /* number of sites in array */
  80.     
  81. } *ParsP;
  82.  
  83.  
  84. typedef struct Vars
  85. {
  86.     char     whichFile[512];
  87.     int        VolNum;
  88.     int        Issue;
  89.     int        itemCount;
  90.     char    header[100];    /* header of digest */
  91.  
  92.     char    nameAll[20];        /* name of the complete digest file */
  93.     char    nameTOC[20];        /* name of the toc only file */
  94.     char    nameProg[20];        /* name of the programs file (either with or without toc) */
  95.     char    nameMess[20];        /* name of the messages file (either with or without toc) */
  96.     
  97. } *VarsP;
  98.  
  99.  
  100. #ifdef __THINK__
  101.  
  102. /**********************************
  103.  
  104.     Mac specific file get function
  105.     
  106. */
  107.  
  108. int GetName( char *name )
  109. {
  110.     SFReply        theReply;
  111.     Point        where;
  112.     SFTypeList    typeList;
  113.  
  114.     typeList[0]='TEXT';            /* file type to search for */
  115.     where.h=20;  where.v=90;    /* SF dialog window position */
  116.  
  117.     SFGetFile(where,0,0L,1,typeList,NULL,&theReply);
  118.  
  119.     if ( theReply.good == TRUE ) 
  120.     { 
  121.         strncpy( name, (char *)(theReply.fName+1), theReply.fName[0] );
  122.         name[theReply.fName[0]]=0;
  123.         return(1);
  124.     }
  125.     else
  126.         return(0);
  127. }
  128.  
  129. #endif
  130.  
  131. /**********************************
  132.  
  133.     Find the DIGEST header and fill-in the volume and issue numbers
  134.     also the header is copied for future use
  135.     
  136. */
  137.  
  138. int findHeader( ParsP p, VarsP v, char *line, int parse )
  139. {
  140.     char    *cptr;
  141.     int    found=0;
  142.     
  143.     /* init header vars */
  144.     
  145.     if(parse)
  146.     {
  147.         v->VolNum=0;
  148.         v->Issue=0;
  149.     }
  150.     
  151.     /* while there is still a line to read find header */
  152.     
  153.     do {    
  154.             if( feof( inP ) )
  155.             {
  156.                 notify("End of file reached.\n");
  157.                 notify("Could not find Begin of Digest (BOD) tag.\n");
  158.                 notify("Closing file ...\n");
  159.                 return(0);
  160.             }
  161.             
  162.             /* check if the line is not empty */
  163.             
  164.             if( fgets( line, 256, inP ) != NULL )
  165.             {
  166.                 /* check for the begin of digest string */
  167.                 
  168.                 if( strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) == 0 )
  169.                 {
  170.                     notify("Found %s\n", p->BegOfDigest);
  171.                     notify(line);
  172.                     
  173.                     strcpy( v->header, line );            /* make a copy for use as heading */
  174.                     
  175.                     found = 1;
  176.                     
  177.                     /* extract volume number */
  178.                     
  179.                     if( parse )
  180.                     {
  181.                         if( p->Volume!=NULL )
  182.                         {
  183.                             if( strlen(p->Volume)>0 )
  184.                             {
  185.                                 cptr = (char *)strstr( line, p->Volume );
  186.                                 if( cptr==NULL )
  187.                                 {
  188.                                     notify("Can't find volume number\n");
  189.                                     notify("Please specify Volume number: ");
  190.                                     scanf("%d", &(v->VolNum));
  191.                                 }
  192.                                 else
  193.                                     v->VolNum = atoi( cptr+strlen(p->Volume) );
  194.                             }
  195.                         }
  196.                         
  197.                         /* extract issue number */
  198.                         
  199.                         if( p->Issue!=NULL )
  200.                         {
  201.                             if( strlen(p->Issue)>0 )
  202.                             {
  203.                                 cptr = (char *)strstr( line, p->Issue );
  204.                                 if( cptr==NULL )
  205.                                 {
  206.                                     notify("Can't find issue number\n");
  207.                                     notify("Please specify Issue number: ");
  208.                                     scanf("%d", &(v->Issue));
  209.                                 }
  210.                                 else
  211.                                     v->Issue = atoi( cptr+strlen(p->Issue) );
  212.                             }
  213.                             else
  214.                             {
  215.                                 notify("Please specify Issue number: ");
  216.                                 scanf("%d", &(v->Issue));
  217.                             }
  218.                         }    
  219.                     }
  220.                 }
  221.             }
  222.     } while( !found );
  223.     
  224.     return(1);
  225. }
  226.  
  227. void GetDestName( char *format, VarsP v, char *name, char *path, char *comment )
  228. {
  229.     char    dummy[200];
  230.     
  231.     if( (v->Issue!=0) && (v->VolNum!=0) )
  232.     {
  233.         sprintf(name, format, v->Issue, v->VolNum );
  234.     }
  235.     else if( (v->Issue!=0 ) )
  236.     {
  237.         sprintf(name, format, v->Issue );
  238.     }
  239.     else
  240.     {
  241.         notify( comment );
  242.         fgets(name,38,stdin);
  243.         
  244.         if( strlen(name)<1 )
  245.         {
  246.             notify("Illegal file name!\n");
  247.             strcpy( name, "digest.html");
  248.             notify("Using default ");
  249.         }
  250.     }
  251.     
  252.     strcpy(dummy, path);
  253.     strcat(dummy, name);
  254.     strcpy(name, dummy);
  255.     notify("name = '%s'\n", name);
  256. }
  257.  
  258. #ifdef __THINK__
  259.                 
  260. void SetupFinderInfo( char *name, OSType type, OSType creator )
  261. {
  262.     Str255     fileName;
  263.     FInfo    fndrInfo;
  264.     
  265.     notify("Setting up finder info for '%s'.\n", name);
  266.     
  267.     strncpy( (char *)fileName+1, name, strlen(name) );
  268.     
  269.     fileName[0] = strlen(name);
  270.     
  271.     if( GetFInfo(fileName,0,&fndrInfo)==0 )
  272.     {
  273.         fndrInfo.fdType = type;
  274.         fndrInfo.fdCreator = creator;
  275.         if( SetFInfo(fileName, 0, &fndrInfo)!=0 )
  276.         {
  277.             notify("OS error setting finder info.\n");
  278.         }
  279.     }
  280.     else
  281.     {
  282.         notify("Couldn't set type creator due to OS error.\n");
  283.     }
  284. }
  285.  
  286. void SetUpAllFinderInfo( ParsP p, VarsP v )
  287. {
  288.     OSType     type, creator;
  289.     int        i;
  290.     OSType     k, test;
  291.     
  292.     
  293.     if( (strlen(p->Ftype)<4) || (strlen(p->Fcreator)<4) )
  294.     {
  295.         notify("Illegal type (FTYPE) and creator (FCREAT) specified.\n");
  296.         notify("Type and creator parameters should be 4 characters long.\n");
  297.         notify("Please, check your parameters file.\n");
  298.         return;
  299.     }
  300.     
  301.     k=1;
  302.     type=0;
  303.     creator=0;
  304.     
  305.     test=255;
  306.     
  307.     if( (char)test!=255 )    /* if little endian */
  308.     {    
  309.         notify("You have a Little Endian processor. Great, so what! Just checking.\n");
  310.  
  311.         for(i=0; i<4; i++)
  312.         {
  313.             type+=(OSType)(p->Ftype[3-i])*k;    
  314.             creator+=(OSType)(p->Fcreator[3-i])*k;
  315.             if(i<3) k *= 256;
  316.         }
  317.     }
  318.     else
  319.     {
  320.         notify("You have a Big Endian processor. Great, so what! Just checking.\n");
  321.  
  322.         for(i=0; i<4; i++)
  323.         {
  324.             type+=(OSType)(p->Ftype[i])*k;    
  325.             creator+=(OSType)(p->Fcreator[i])*k;
  326.             if(i<3) k *= 256;
  327.         }
  328.     }
  329.  
  330.     notify("Type: '%s', Creator '%s'.\n", p->Ftype, p->Fcreator);
  331.  
  332.     switch( p->Type )                        
  333.     {
  334.         case 1:        /* type 1: the entire digest in 1 file */
  335.         
  336.                 SetupFinderInfo( v->nameAll, type, creator );
  337.         break;
  338.         
  339.         case 2:        /* type 2: topics, programs and messages as separate files */
  340.         
  341.                 SetupFinderInfo( v->nameTOC, type, creator );
  342.                 if( p->Files )
  343.                 {
  344.                     SetupFinderInfo( v->nameProg, type, creator );
  345.                 }
  346.                 SetupFinderInfo( v->nameMess, type, creator );
  347.         break;
  348.         
  349.         case 3:        /* type 3: toc + progs, toc + mes */
  350.         
  351.                 /* toc + progs files */
  352.                 
  353.                 if( p->Files )
  354.                 {
  355.                     SetupFinderInfo( v->nameProg, type, creator );
  356.                 }
  357.                 
  358.                 SetupFinderInfo( v->nameMess, type, creator );
  359.         break;
  360.     }
  361.  
  362. }
  363.  
  364. #endif
  365.  
  366.  
  367.  
  368. int SetUpFiles( ParsP p, VarsP v )
  369. {
  370.     char    name[200];
  371.     
  372.     /* set-up output files */
  373.     
  374.     switch( p->Type )                        
  375.     {
  376.         case 1:        /* type 1: the entire digest in 1 file */
  377.         
  378.                 notify("Type 1:\n");
  379.                 
  380.                 GetDestName( p->nameAll, v, name, p->destPath,
  381.                             "Please specify destination file name for entire digest: " );
  382.                 strcpy( v->nameAll, name );
  383.                 
  384.                 if( (outTMes = fopen( name,"w")) == NULL )
  385.                 {
  386.                     notify( "Can't open '%s'\n", name );
  387.                     return(0);
  388.                 }
  389.                 
  390.                 if(debug)
  391.                     notify( "outTMes = %x\n", outTMes );
  392.                 
  393.                 outTPrg = NULL;
  394.                 outMes = NULL;
  395.                 outPrg = NULL;
  396.         break;
  397.         
  398.         case 2:        /* type 2: topics, programs and messages as separate files */
  399.         
  400.                 notify("Type 2:\n");
  401.                 
  402.                 GetDestName( p->nameTOC, v, name, p->destPath,
  403.                             "Please specify destination file name for topics: " );
  404.                   strcpy( v->nameTOC, name );
  405.               
  406.                   if( (outTMes = fopen( name,"w")) == NULL )
  407.                   {
  408.                     notify("Can't open '%s'\n", name );
  409.                       return(0);
  410.                   }
  411.               
  412.                   outTPrg = NULL;
  413.  
  414.                 if( p->Files )
  415.                 {
  416.                     GetDestName( p->nameProg, v, name, p->destPath,
  417.                                 "Please specify destination file name for programs: " );
  418.                       strcpy( v->nameProg, name );
  419.                   
  420.                       if( (outPrg = fopen( name,"w")) == NULL )
  421.                       {
  422.                         notify("Can't open '%s'\n", name );
  423.                           return(0);
  424.                       }
  425.  
  426.                 }
  427.                 
  428.                 GetDestName( p->nameMess, v, name, p->destPath,
  429.                             "Please specify destination file name for messages: " );
  430.                   strcpy( v->nameMess, name );
  431.               
  432.                   if( (outMes = fopen( name,"w")) == NULL )
  433.                   {
  434.                       notify("Can't open '%s'\n", name );
  435.                       return(0);
  436.                   }
  437.               
  438.         break;
  439.         
  440.         case 3:        /* type 3: toc + progs, toc + mes */
  441.         
  442.                 /* toc + progs files */
  443.                 
  444.                 if( p->Files )
  445.                 {
  446.                     GetDestName( p->nameProg, v, name, p->destPath,
  447.                                 "Please specify destination file name for programs: " );
  448.                     strcpy( v->nameProg, name );
  449.               
  450.                     if( (outTPrg = fopen( name,"w")) == NULL )
  451.                     {
  452.                         notify("Can't open '%s'\n", name );
  453.                         return(0);
  454.                     }
  455.                 }
  456.                 
  457.                 outPrg = NULL;
  458.                 
  459.                 /* toc + messages files */
  460.                 
  461.                 GetDestName( p->nameMess, v, name, p->destPath,
  462.                             "Please specify destination file name for messages: " );
  463.                   strcpy( v->nameMess, name );
  464.                 
  465.                 if( (outTMes = fopen( name,"w")) == NULL )
  466.                 {
  467.                     notify("Can't open '%s'\n", name );
  468.                     return(0);
  469.                 }
  470.                 
  471.                 outMes = NULL;              
  472.         break;
  473.         
  474.         default:
  475.                 notify( "Type of digest has not been specified, please check digester.par file.\n");
  476.                 return(0);
  477.         break;
  478.     }
  479.  
  480.     return(1);
  481. }
  482.  
  483.  
  484. void SetUpTitle( VarsP v, FILE *out, char *Message )
  485. {
  486.     if( out != NULL )
  487.     {
  488.         fprintf(out,"<TITLE>Volume %d : Issue %d</TITLE>\n", v->VolNum, v->Issue);
  489.         fprintf(out,"<pre>\n\n");
  490.         fprintf(out,"<a href=index.html#issue%d-%d><img src=digester.gif alt=Index></a> %s",
  491.                         v->Issue+1, v->VolNum, Message);
  492.         
  493.         fprintf(out,"</pre>\n\n");
  494.         fprintf(out,"<hr>\n\n");
  495.     }
  496. }
  497.  
  498. char *findALink( char *line )
  499. {
  500.     char *cptr;
  501.     
  502.     if( (cptr=strstr(line, "http://"))!=NULL )         return(cptr);
  503.     if( (cptr=strstr(line, "ftp://"))!=NULL )         return(cptr);
  504.     if( (cptr=strstr(line, "mailto:"))!=NULL )         return(cptr);
  505.     if( (cptr=strstr(line, "gopher://"))!=NULL )     return(cptr);
  506.  
  507.     return(NULL);
  508. }
  509.  
  510. void linkLine( char *line )
  511. {
  512.     char    *cptr, *bptr, tempLine[512], resultLine[512];
  513.     int        found;
  514.     
  515.     cptr = line;
  516.     resultLine[0]=0;
  517.     
  518.     do {
  519.         found=0;
  520.         bptr=cptr;
  521.         
  522.         if( (cptr=findALink(bptr))!=NULL )
  523.         {
  524.             found=1;
  525.             if(debug) puts("found URL");
  526.             strncpy(tempLine, bptr, cptr-bptr);    /* copy preceeding stuff */
  527.             tempLine[cptr-bptr]=0;
  528.             strcat(resultLine, tempLine);
  529.             bptr=cptr;
  530.             while(     (*cptr!=0) && (*cptr!='\n')        /* find delimiter */
  531.                     && ( (*cptr=='.') || (*cptr=='~') || (*cptr=='/') || (*cptr=='@') 
  532.                          || (*cptr==':') || (*cptr=='-') || (*cptr=='+') || (*cptr=='_')
  533.                          || ((*cptr>='a') && (*cptr<='z'))
  534.                          || ((*cptr>='A') && (*cptr<='Z'))
  535.                          || ((*cptr>='0') && (*cptr<='9'))
  536.                        )
  537.                  ) cptr++;
  538.             strncpy(tempLine, bptr, cptr-bptr);    /* copy link */
  539.             tempLine[cptr-bptr]=0;
  540.             strcat(resultLine, "<a href=");
  541.             strcat(resultLine, tempLine);
  542.             strcat(resultLine, ">");
  543.             strcat(resultLine, tempLine);
  544.             strcat(resultLine, "</a>");
  545.         }
  546.     } while( found );
  547.     
  548.     if( bptr==line ) return;                    /* nothing happened */
  549.     strcat( resultLine, bptr );                    /* copy rest of the line */
  550.     strcpy( line, resultLine );                    /* copy it back */
  551. }
  552.  
  553.  
  554. void filterEntities( char *line )
  555. {
  556.     char     tempLine[512];
  557.     int    l, i;
  558.     
  559.     tempLine[0]=0;
  560.     l = 0;
  561.     for(i=0; i<strlen(line); i++ )
  562.     {
  563.         if( line[i]=='<' )
  564.         {
  565.             tempLine[l++] = '&';
  566.             tempLine[l++] = 'l';
  567.             tempLine[l++] = 't';
  568.             tempLine[l++] = ';';
  569.         }
  570.         else
  571.         if( line[i]=='>' )
  572.         {
  573.             tempLine[l++] = '&';
  574.             tempLine[l++] = 'g';
  575.             tempLine[l++] = 't';
  576.             tempLine[l++] = ';';
  577.         }
  578.         else
  579.         if( line[i]=='"' )
  580.         {
  581.             tempLine[l++] = '&';
  582.             tempLine[l++] = 'q';
  583.             tempLine[l++] = 'u';
  584.             tempLine[l++] = 'o';
  585.             tempLine[l++] = 't';
  586.             tempLine[l++] = ';';
  587.         }
  588.         else
  589.         if( line[i]=='&' )
  590.         {
  591.             tempLine[l++] = '&';
  592.             tempLine[l++] = 'a';
  593.             tempLine[l++] = 'm';
  594.             tempLine[l++] = 'p';
  595.             tempLine[l++] = ';';
  596.         }
  597.         else
  598.         {
  599.             tempLine[l++] = line[i];
  600.             tempLine[l] = 0;
  601.         }
  602.     }
  603.     strcpy( line, tempLine );
  604. }
  605.  
  606.  
  607. int SkipTOC( ParsP p, VarsP v, int addInfo )
  608. {
  609.     int     found;
  610.     char    line[256];
  611.  
  612.     found = 0;
  613.     
  614.     if( strlen(p->BeginOfTopics)<1 )
  615.     {
  616.         /* don't bother with TOC */
  617.         if( strlen(p->EndOfTopics)>0 )
  618.         {
  619.             do {
  620.                 if( fgets( line, 256, inP ) != NULL )
  621.                 if(strstr( line, p->EndOfTopics ) != NULL)
  622.                 {
  623.                     if( debug )
  624.                         notify( "Found end of Topics\n");
  625.                         
  626.                     return(1);
  627.                 }
  628.             } while( !feof(inP ) );
  629.             
  630.             notify("Couldn't find the begining of the messages.\n");
  631.             notify("Please, check the digester.par file EOT tag.\n");
  632.             
  633.             return(0);
  634.         }
  635.         
  636.         notify("No BOT or EOT tag in digester.par\n");
  637.         
  638.         return(1);
  639.     }
  640.     
  641.     do {
  642.             if( fgets( line, 256, inP ) != NULL )
  643.             {
  644.                 if( strstr( line, p->BeginOfTopics ) != NULL )
  645.                 {
  646.                     if( debug )
  647.                         notify( "Found begin of Topics\n");
  648.                         
  649.                     found = 1;
  650.                 }
  651.                 
  652.                 if(strstr( line, p->EndOfTopics ) != NULL)
  653.                 {
  654.                     if( debug )
  655.                         notify( "Found end of Topics\n");
  656.                         
  657.                     return(1);
  658.                 }
  659.             }
  660.             else
  661.             {                    
  662.                 return(0);
  663.             }
  664.     } while( !found );
  665.  
  666.     fgets( line, 256, inP ); /* get empty line */
  667.  
  668.     /* skip TOC */
  669.     
  670.     do{
  671.         fgets( line, 256, inP );
  672.     }while( (strlen(line)>1) 
  673.             && !feof(inP)
  674.             && (strstr( line, p->EndOfTopics ) == NULL)
  675.            );
  676.  
  677.     if(debug)
  678.         notify("TOC skipped\n");
  679.  
  680.     if( strstr( line, p->EndOfTopics ) != NULL ) return(1);
  681.     
  682.     /* Now copy all lines to message files */
  683.     
  684.     if( outTMes!=NULL && addInfo==1 )
  685.         fputs( "<HR><P><PRE>", outTMes );
  686.  
  687.     if( outTPrg!=NULL && addInfo==1 )
  688.         fputs( "<HR><P><PRE>", outTPrg );
  689.     
  690.     do
  691.     {
  692.         fgets( line, 256, inP );
  693.         filterEntities(line);
  694.         if( p->URLs ) linkLine( line );
  695.         
  696.         if( outTMes!=NULL && addInfo==1 )
  697.             fputs( line, outTMes );
  698.             
  699.         if( outTPrg!=NULL && addInfo==1 )
  700.             fputs( line, outTPrg );
  701.     }
  702.     while( (strstr( line, p->EndOfTopics ) == NULL ) && !feof(inP) );
  703.  
  704.     if( outTMes!=NULL && addInfo==1 )
  705.         fputs( "</PRE>", outTMes );
  706.  
  707.     if( outTPrg!=NULL && addInfo==1 )
  708.         fputs( "</PRE>", outTPrg );
  709.     
  710.     if( feof(inP) )
  711.     {
  712.         notify( "Cannot find end of Topics phrase ... aborting\n");
  713.         return(0);
  714.     }
  715.     
  716.     if(debug)
  717.         notify("Found end of TOC\n");
  718.  
  719.     return(1);
  720. }
  721.  
  722. void DoFTPMessage( ParsP p, FILE *outP )
  723. {
  724.     int i;
  725.     char    name[20];
  726.     
  727.     fputs("\n<HR>\n<CENTER>\n", outP);
  728.     fputs("<H4>Direct FTP to mirror site</H4>", outP);
  729.     fputs("</CENTER>\n", outP);
  730.     
  731.     fprintf(outP, "Make FTP connection with: ");
  732.     strcpy( name, "/info-mac/");
  733.  
  734.     for(i=0; i<p->nSites; i++)
  735.     {
  736.         fputs( "", outP );
  737.         fprintf( outP, p->sites+i*LINELENGTH, name);
  738.     }        
  739.  
  740.     fputs( ".\n<P><HR><P>\n", outP );
  741. }
  742.  
  743. int MakeTOC(ParsP p, VarsP v, char *line)
  744. {
  745.     int        msgItem;
  746.     char    subject[80];
  747.     char    topic[40];
  748.     int        found;
  749.     
  750.     msgItem = 0;
  751.     
  752.     if( outTMes==NULL )
  753.     {
  754.         notify( "Error in making TOC, Message output file is not open (pointer NULL)\n\n");
  755.         return(0);
  756.     }
  757.         
  758.     if( outTPrg != NULL )
  759.     {
  760.         fputs( "<HR><CENTER>", outTPrg );
  761.         fputs( "<HR><CENTER>", outTMes );
  762.         fputs( "<H3>Programs: Table of Contents</H3>", outTPrg );
  763.         fputs( "<H3>Messages: Table of Contents</H3>", outTMes );
  764.         fputs( "</CENTER><HR>", outTPrg );
  765.         fputs( "</CENTER><HR>", outTMes );
  766.         fputs( "<UL>", outTPrg );
  767.         fputs( "<UL>", outTMes );
  768.     }
  769.     else
  770.     {
  771.         fputs( "<HR><CENTER>", outTMes );
  772.         fputs( "<H3>Table of Contents</H3>", outTMes );
  773.         fputs( "</CENTER><HR>", outTMes );
  774.         fputs( "<UL>", outTMes );
  775.     }
  776.     
  777.     do{
  778.         msgItem++;
  779.         
  780.         strcpy( subject, "" );        /* default */
  781.         found=0;
  782.         
  783.         fgets( line, 256, inP );
  784.         while( (strncmp( line, p->EndOfMessage, strlen(p->EndOfMessage) )!=0) &&
  785.                  (strstr( line, p->BegOfDigest ) == NULL) && 
  786.                  (strstr( line, p->EndOfDigest ) == NULL) && 
  787.                  !feof(inP) )
  788.         {
  789.             filterEntities( line );
  790.             
  791.             if( (strncmp( line, "From: ", strlen( "From: " ) )==0)
  792.                 && !found )
  793.             {
  794.                 strcpy( subject, "(NO SUBJECT)" );        /* default */
  795.                 v->whichFile[msgItem]='m';
  796.             }
  797.                 
  798.             /* find subject */
  799.             if( (strncmp( line, "Subject: ", strlen( "Subject: " ) )==0)
  800.                 && !found )
  801.             {
  802.                 strncpy( subject, line+strlen( "Subject: " ), 78);
  803.                 subject[79]=0;
  804.                 found=1;
  805.             }
  806.             
  807.             if( p->Files )
  808.             if( strstr( line, p->BegOfFile ) != NULL )
  809.             {
  810.                 if(debug)
  811.                     notify("Found file link for item %d!\n", msgItem);
  812.                 
  813.                 v->whichFile[msgItem]='p';
  814.             }
  815.             
  816.             fgets( line, 256, inP );
  817.         }    /* while not end of message */
  818.         
  819.         /* end of message, write TOC entry */
  820.  
  821.         if( subject[0]!=0 )        /* check if there is a subject anyway */
  822.         {
  823.             /* set correct icon */
  824.             if( v->whichFile[msgItem] == 'p' )
  825.                 strcpy(topic, "<IMG SRC=prog_topic.gif ALT=Program> ");
  826.             else
  827.                 strcpy(topic, "<IMG SRC=msg_topic.gif ALT=Message> ");
  828.             
  829.             if( !p->Buttons )
  830.                 strcpy( topic, "<LI> " );
  831.                 
  832.             switch( p->Type )
  833.             {
  834.                 case 1:
  835.                     fprintf(outTMes, "%s<a name=toc%d> </a><a href=#item%d>%s</a>\n",
  836.                                             topic, msgItem, msgItem, subject);
  837.                             
  838.                     if( p->Buttons )
  839.                         fputs( "<BR>\n", outTMes );
  840.                 break;
  841.                 
  842.                 case 2:
  843.                     if( v->whichFile[msgItem]=='m' )
  844.                         fprintf(outTMes, "%s<a name=toc%d> </a><a href=%s#item%d>%s</a>\n",
  845.                                                 topic, msgItem, v->nameMess, msgItem, subject);
  846.                     else
  847.                         fprintf(outTMes, "%s<a name=toc%d> </a><a href=%s#item%d>%s</a>\n",
  848.                                                 topic, msgItem, v->nameProg, msgItem, subject);
  849.                             
  850.                     if( p->Buttons )
  851.                         fputs( "<BR>\n", outTMes );
  852.                 break;
  853.                 
  854.                 case 3:
  855.                     if( v->whichFile[msgItem]=='m' )
  856.                     {
  857.                         fprintf(outTMes, "%s<a name=toc%d> </a><a href=#item%d>%s</a>\n",
  858.                                                 topic, msgItem, msgItem, subject);
  859.                             
  860.                         if( p->Buttons )
  861.                             fputs( "<BR>\n", outTMes );
  862.                     }
  863.                     else
  864.                     {
  865.                         fprintf(outTPrg, "%s<a name=toc%d> </a><a href=#item%d>%s</a>\n",
  866.                                                 topic, msgItem, msgItem, subject);
  867.                             
  868.                         if( p->Buttons )
  869.                             fputs( "<BR>\n", outTPrg );
  870.                     }
  871.                     
  872.                     
  873.                 break;
  874.                 
  875.                 default:
  876.                     return(0);    /* error occured: illegal type specified */
  877.                 break;
  878.                 
  879.             }
  880.         }
  881.         
  882.     }while( (strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) != 0) 
  883.             && (strstr( line, p->EndOfDigest ) == NULL) 
  884.                 && !feof( inP ) );
  885.                 
  886.     if( p->Type==3 )    /* make link between program and Q&A files */
  887.     {
  888.         if( !p->Buttons )
  889.         {
  890.             fprintf( outTMes, "<LI> " );
  891.             fprintf( outTPrg, "<LI> " );
  892.         }
  893.         else
  894.         {
  895.             fprintf( outTMes, "<IMG SRC=prog_topic.gif ALT=Program> ");
  896.             fprintf( outTPrg, "<IMG SRC=msg_topic.gif ALT=Message> ");
  897.                             
  898.         }
  899.         fprintf( outTMes, "<a href=%s>[*] PROGRAMS TABLE OF CONTENTS</a><BR>\n", v->nameProg );
  900.         fprintf( outTPrg, "<a href=%s>MESSAGES TABLE OF CONTENTS</a><BR>\n", v->nameMess );
  901.  
  902.     }
  903.  
  904.     if( outTMes!=NULL ) fputs( "</UL>\n<P>\n", outTMes );
  905.     if( outTPrg!=NULL ) fputs( "</UL>\n<P>\n", outTPrg );
  906.     
  907.  
  908.     /* write intro */
  909.     
  910.     if(p->Files)
  911.     {
  912.     switch( p->Type )
  913.     {
  914.         case 1:
  915.             DoFTPMessage( p, outTMes );
  916.         break;
  917.  
  918.         case 2:
  919.             DoFTPMessage( p, outTMes );
  920.         break;
  921.  
  922.         case 3:
  923.             DoFTPMessage( p, outTPrg );
  924.         break;
  925.     }
  926.     }
  927.     else
  928.     {
  929.         if( outTMes!=NULL)
  930.             fputs( ".\n<P><HR><P>\n", outTMes );
  931.     }
  932.  
  933.     return(1);
  934. }
  935.  
  936. void FetchAddress( char *cptr, char *address )
  937. {
  938.     strcpy(address, cptr);
  939.     if( (cptr=strstr(address,"\n")) != NULL)
  940.         *cptr=0;
  941.  
  942.     if( (cptr=strstr(address,"<")) != NULL)
  943.     {
  944.         strcpy(address, cptr+1);
  945.         if( (cptr=strstr(address,">")) != NULL)
  946.             *cptr=0;
  947.     }
  948.  
  949.     if( (cptr=strstr(address," ")) != NULL)
  950.         *cptr=0;
  951. }
  952.  
  953. int DoMessages(ParsP p, VarsP v, char *line)
  954. {
  955.     int        msgItem;
  956.     char    topic[40];
  957.     char    next[40];
  958.     char    prev[40];
  959.     char    toc[40];
  960.     char    post[40];
  961.     char    index[40];
  962.     char    address[256];
  963.     FILE    *outP;
  964.     char    name[80], *bptr, *eptr;
  965.     int        i, pre;
  966.     char     filteredLine[256];
  967.     
  968.     if( p->Buttons )
  969.     {
  970.         strcpy( next, "<img src=next.gif alt=Next>");
  971.         strcpy( prev, "<img src=prev.gif alt=Previous>");
  972.         strcpy( toc, "<img src=toc.gif alt=TOC>");
  973.         strcpy( post, "<img src=post.gif alt=MakeReply>");
  974.         strcpy( index, "<img src=digester.gif alt=Index>");
  975.     }
  976.     else
  977.     {
  978.         strcpy( next, "Next" );
  979.         strcpy( prev, "Previous" );
  980.         strcpy( toc, "Table of Contents" );
  981.         strcpy( post, "Select Message for Posting" );
  982.         strcpy( index, "Back to INDEX" );
  983.     }
  984.     
  985.     msgItem = 0;
  986.  
  987.     /* do messages */
  988.     
  989.     do{
  990.         msgItem++;
  991.  
  992.         /* choose destination file */        
  993.  
  994.         switch( p->Type )
  995.         {
  996.             case 1:
  997.                 outP = outTMes;
  998.             break;
  999.             
  1000.             case 2:
  1001.                 if( (v->whichFile[msgItem]=='m') || (outPrg==NULL) )
  1002.                     outP = outMes;
  1003.                 else
  1004.                     outP = outPrg;
  1005.             break;
  1006.             
  1007.             case 3:
  1008.                 if( (v->whichFile[msgItem]=='m')  || (outPrg==NULL) )
  1009.                     outP = outTMes;
  1010.                 else
  1011.                     outP = outTPrg;
  1012.             break;
  1013.         }
  1014.         
  1015.         if( outP == NULL )
  1016.         {
  1017.             notify("Output file not open!!\n");
  1018.             return(0);
  1019.         }
  1020.  
  1021.         /* label the thing */
  1022.         fprintf( outP, "<a name=item%d> </a> ", msgItem);
  1023.         
  1024.         /* write navigation panel */
  1025.         if( v->whichFile[msgItem]!='0' )
  1026.         switch( p->Type )
  1027.         {
  1028.             case 1:
  1029.                 fprintf( outP, "<a href=#item%d>%s</a> ", msgItem+1, next);
  1030.                 if( msgItem>1) fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev );
  1031.                 fprintf( outP, "<a href=#toc%d>%s</a> ", msgItem, toc);
  1032.                 if(p->Mail) fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ", 
  1033.                                             p->scriptPath, msgItem, v->nameAll, post);
  1034.             break;
  1035.  
  1036.             case 2:
  1037.                 if(v->whichFile[msgItem+1]!='0') 
  1038.                 {
  1039.                     if( v->whichFile[msgItem+1]!=v->whichFile[msgItem])
  1040.                     {
  1041.                         if( v->whichFile[msgItem+1]=='m' )
  1042.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1043.                                         v->nameMess, msgItem+1, next);
  1044.                         else
  1045.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1046.                                         v->nameProg, msgItem+1, next);
  1047.                     }
  1048.                     else
  1049.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem+1, next);
  1050.                 }
  1051.                 
  1052.                 if( msgItem>1 && (v->whichFile[msgItem-1]!='0') )
  1053.                 {
  1054.                     if( v->whichFile[msgItem-1]!=v->whichFile[msgItem] )
  1055.                     {
  1056.                         if( v->whichFile[msgItem-1]=='m' )
  1057.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1058.                                                 v->nameMess, msgItem-1, prev);
  1059.                         else
  1060.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1061.                                                 v->nameProg, msgItem-1, prev);
  1062.                     }
  1063.                     else 
  1064.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1065.                 }
  1066.  
  1067.                 fprintf( outP, "<a href=%s#toc%d>%s</a> ", v->nameTOC, msgItem, toc);
  1068.  
  1069.                 if( p->Mail )
  1070.                     if( v->whichFile[msgItem]=='m' )
  1071.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1072.                                          p->scriptPath, msgItem, v->nameMess, post);
  1073.                     else
  1074.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1075.                                          p->scriptPath, msgItem, v->nameProg, post);
  1076.  
  1077.             break;
  1078.  
  1079.             case 3:
  1080.                 if(v->whichFile[msgItem+1]!='0') 
  1081.                 {
  1082.                     if(v->whichFile[msgItem+1]!=v->whichFile[msgItem] )
  1083.                     {
  1084.                         if( v->whichFile[msgItem+1]=='m' )
  1085.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1086.                                         v->nameMess, msgItem+1, next);
  1087.                         else
  1088.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1089.                                         v->nameProg, msgItem+1, next);
  1090.                     }
  1091.                     else
  1092.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem+1, next);
  1093.                 }
  1094.                 
  1095.                 if( (msgItem>1) && (v->whichFile[msgItem-1]!='0') ) 
  1096.                 {
  1097.                     if( v->whichFile[msgItem-1]!=v->whichFile[msgItem] )
  1098.                     {
  1099.                         if( v->whichFile[msgItem-1]=='m' )
  1100.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1101.                                                 v->nameMess, msgItem-1, prev);
  1102.                         else
  1103.                             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1104.                                                 v->nameProg, msgItem-1, prev);
  1105.                     }
  1106.                     else 
  1107.                         fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1108.                 }
  1109.  
  1110.                 fprintf( outP, "<a href=#toc%d>%s</a> ", msgItem, toc);
  1111.  
  1112.                 if( p->Mail )
  1113.                     if( v->whichFile[msgItem]=='m' )
  1114.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1115.                                          p->scriptPath, msgItem, v->nameMess, post);
  1116.                     else
  1117.                         fprintf( outP, "<a href=%spost-send?%d,%s>%s</a> ",
  1118.                                          p->scriptPath, msgItem, v->nameProg, post);
  1119.  
  1120.             break;
  1121.         }
  1122.  
  1123.         if( v->whichFile[msgItem]!='0' )
  1124.         fprintf( outP, "<a href=index.html#issue%d-%d>%s</a>\n\n", 
  1125.                                 v->Issue+1, v->VolNum, index);
  1126.  
  1127.         /* end of navigation bar, now do the message */
  1128.  
  1129.         fputs( "\n<PRE>", outP);
  1130.         pre=1;
  1131.         
  1132.         fgets( line, 256, inP );
  1133.         while( (strncmp( line, p->EndOfMessage, strlen(p->EndOfMessage) )!=0) &&
  1134.                  (strstr( line, p->BegOfDigest ) == NULL) && 
  1135.                  (strstr( line, p->EndOfDigest ) == NULL) && 
  1136.                  !feof(inP) )
  1137.         {
  1138.  
  1139.             if( v->whichFile[msgItem]!='0' )
  1140.             {
  1141.                 strcpy( filteredLine, line );
  1142.                 filterEntities( filteredLine );
  1143.                 if( p->URLs ) linkLine( filteredLine );
  1144.     
  1145.                 /* find Subject, Date or From */
  1146.                 if( (strncmp( line, "Subject: ", strlen( "Subject: " ) )==0) ||
  1147.                      (strncmp( line, "Date: ", strlen( "Date: " ) )==0) ||
  1148.                      (strncmp( line, "From: ", strlen( "From: " ) )==0) ||
  1149.                      (strncmp( line, "To: ", strlen( "To: " ) )==0)
  1150.                   )
  1151.                 {
  1152.                     if( pre ) fprintf( outP, "</PRE>");
  1153.                     pre=0;
  1154.                     if( strncmp( line, "From: ", strlen( "From: " ) )==0 )
  1155.                     {
  1156.                         FetchAddress( line+strlen( "From: " ), address );
  1157.                         fprintf( outP, "From: <a href=mailto:%s>%s</a><BR>\n", 
  1158.                                         address, address );
  1159.  
  1160.                     }
  1161.                     else if(strncmp( line, "To: ", strlen( "To: " ) )==0)
  1162.                     {
  1163.                         FetchAddress( line+strlen( "To: " ), address );
  1164.                         fprintf( outP, "To: <a href=mailto:%s>%s</a><BR>\n", 
  1165.                                         address, address );
  1166.  
  1167.                     }
  1168.                     else
  1169.                     {
  1170.                         fprintf( outP, "%s\n<BR>\n", line);
  1171.                     }
  1172.                 }
  1173.                 else
  1174.                 {
  1175.                     if( !pre ) fprintf( outP, "<PRE>");
  1176.                     pre=1;
  1177.                     
  1178.                     fputs(filteredLine, outP);
  1179.     
  1180.                     /* check for begin of file */
  1181.                     
  1182.                     if( (strstr( line, p->BegOfFile ) != NULL) && p->Files )
  1183.                     {
  1184.                         if(debug)
  1185.                             notify("Found file link for item %d!\n", msgItem);
  1186.                     
  1187.                         bptr=strstr( line, p->RootPath );
  1188.                         eptr=strstr( line, p->EndOfFile );
  1189.     
  1190.                         if( bptr!=NULL && eptr!=NULL )
  1191.                         {
  1192.                             strncpy(name, bptr, eptr-bptr);
  1193.                             name[eptr-bptr]=0;
  1194.                     
  1195.                             fprintf( outP, "\n</pre>\nFetch from " );
  1196.     
  1197.     
  1198.                             for(i=0; i<p->nSites; i++)
  1199.                             {
  1200.                                 fprintf( outP, "\n");
  1201.                                 fprintf( outP, p->sites+i*LINELENGTH, name);
  1202.                             }        
  1203.     
  1204.                             fprintf( outP, ".\n<pre>\n" );
  1205.                         }
  1206.                         else
  1207.                         {
  1208.                             notify("Failed to make link, sorry :(\n");
  1209.                         }
  1210.                     }
  1211.                 }
  1212.             }
  1213.             fgets( line, 256, inP );
  1214.         }    /* while not end of message */
  1215.         
  1216.         fputs("</PRE>\n<HR>", outP );
  1217.         
  1218.     } while( (strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) != 0) 
  1219.                 && (strstr( line, p->EndOfDigest ) == NULL) 
  1220.                 && !feof( inP )
  1221.             );
  1222.  
  1223.     /* write last navigation panel */
  1224.     
  1225.     msgItem++;
  1226.     
  1227.     /* label the thing */
  1228.     fprintf( outP, "<a name=item%d> </a> ", msgItem);
  1229.  
  1230.     if( debug )
  1231.         notify( "Doing Message %d ...\n", msgItem );
  1232.     
  1233.     switch( p->Type )
  1234.     {
  1235.         case 1:
  1236.             if( msgItem>1) fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1237.             fprintf( outP, "<a href=#toc1>%s</a> ", toc);
  1238.         break;
  1239.     
  1240.         case 2:
  1241.             fprintf( outP, "<a href=%s#item%d>%s</a> ", 
  1242.                                 v->nameMess, msgItem-1, prev);
  1243.     
  1244.             fprintf( outP, "<a href=%s#toc1>%s</a> ", v->nameMess, toc);
  1245.         break;
  1246.     
  1247.         case 3:
  1248.             fprintf( outP, "<a href=#item%d>%s</a> ", msgItem-1, prev);
  1249.             fprintf( outP, "<a href=#toc1>%s</a> ", toc);
  1250.         break;
  1251.     }
  1252.     
  1253.     fprintf( outP, "<a href=index.html#issue%d-%d>%s</a>\n\n", 
  1254.                             v->Issue+1, v->VolNum, index);
  1255.     
  1256.     notify( "Messages done.\n");
  1257.  
  1258.     if( (strncmp( line, p->BegOfDigest, strlen(p->BegOfDigest) ) == 0) )
  1259.     {
  1260.         notify("Found new begin of digest...\n");
  1261.         notify("Please, only use one digest per file.\n");
  1262.         notify("This version of DIGESTER does not work with multiple digests files.\n");
  1263.     }
  1264.  
  1265.  
  1266.     return(1);
  1267. }
  1268.  
  1269. void WriteTrailer( FILE *outP )
  1270. {
  1271.  
  1272.     fputs("<p><hr><p>\n", outP);
  1273.     fputs("HTML file created by digester 2.0<p>\n", outP);
  1274.     fprintf(outP,"Digester developed by: <a href=%s>André  C. van der Ham</a><p>\n", DRE);
  1275.     fputs("<address>\n", outP);
  1276.     fputs("Send bug reports, questions, etc. to: A.C.vanderHam@ET.TUDelft.NL<p>\n", outP);
  1277.     fputs("</address>\n", outP);    
  1278. }
  1279.  
  1280.  
  1281. /***************************************
  1282.  
  1283.     Parse one digest at a time
  1284.     returns 1 if there is still data left after the end-of-digest phrase
  1285.     
  1286. */
  1287.  
  1288. void ParseOne( ParsP p, char *digestName )
  1289. {
  1290.     char    line[512];
  1291.     char    name[256];
  1292.     int        i;
  1293.     struct Vars    v, *vp;
  1294.     
  1295.     vp = &v;                                        /* set pointer to variables struct */
  1296.     
  1297.     for(i=0; i<512; i++)                        /* init destination of all messages to nowhere */
  1298.         v.whichFile[i]='0';
  1299.     
  1300.     /* initialize all file pointers */
  1301.     
  1302.     outTPrg =    NULL;
  1303.     outTMes =    NULL;
  1304.     outPrg  =    NULL;
  1305.     outMes  =    NULL;
  1306.  
  1307.     /*  B E G I N   O F   P A S S  1 */
  1308.  
  1309.     notify("PASS1: '%s'...\n", digestName);
  1310.  
  1311.     if( (inP = fopen( digestName, "r" )) == NULL )
  1312.     {
  1313.         notify("Cannot open '%s'\n", digestName);
  1314.         notify("Please make sure '%s' is in the same folder as digester.\n", digestName);
  1315.         return;
  1316.     }
  1317.     
  1318.     notify("Parsing...\n");
  1319.             
  1320.     if( findHeader( p, vp, line, 1 )==0 )    /* set-up header */
  1321.         return;
  1322.  
  1323.     if(debug)
  1324.         notify("Title found\n");
  1325.  
  1326.     if( SetUpFiles( p, vp )==0 )    /* set-up output files */
  1327.     {
  1328.         if( outTPrg!=NULL ) fclose( outTPrg );
  1329.         if( outTMes!=NULL ) fclose( outTMes );
  1330.         if( outPrg!=NULL )  fclose( outPrg );
  1331.         if( outMes!=NULL )  fclose( outMes );
  1332.         if( inP!=NULL )     fclose( inP );
  1333.         return;
  1334.     }
  1335.     
  1336.     if( debug )
  1337.     {
  1338.         notify( "outTPrg = %x\n", outTPrg );
  1339.         notify( "outTMes = %x\n", outTMes );
  1340.         notify( "outPrg = %x\n", outPrg );
  1341.         notify( "outMes = %x\n", outMes );
  1342.     }
  1343.     
  1344.  
  1345.     if( outTPrg!=NULL )
  1346.         SetUpTitle( vp, outTPrg, line );
  1347.  
  1348.     if( outTMes!=NULL )
  1349.         SetUpTitle( vp, outTMes, line );
  1350.  
  1351.     if( SkipTOC( p, vp, 0 ) == 0 )
  1352.     {
  1353.         if( outTPrg!=NULL ) fclose( outTPrg );
  1354.         if( outTMes!=NULL ) fclose( outTMes );
  1355.         if( outPrg!=NULL )  fclose( outPrg );
  1356.         if( outMes!=NULL )  fclose( outMes );
  1357.         if( inP!=NULL )     fclose( inP );
  1358.         return;
  1359.     }
  1360.     
  1361.     if( MakeTOC( p, vp, line )==0 )
  1362.     {
  1363.         if( outTPrg!=NULL ) fclose( outTPrg );
  1364.         if( outTMes!=NULL ) fclose( outTMes );
  1365.         if( outPrg!=NULL )  fclose( outPrg );
  1366.         if( outMes!=NULL )  fclose( outMes );
  1367.         return;
  1368.     }
  1369.  
  1370.     fclose( inP );
  1371.  
  1372.     /*  E N D   O F   P A S S  1 */
  1373.     
  1374.     notify("PASS2: '%s'...\n", digestName);
  1375.     
  1376.     if( (inP = fopen( digestName, "r" )) == NULL )
  1377.     {
  1378.         notify("Cannot open '%s',\n");
  1379.         return;
  1380.     }
  1381.     
  1382.     notify("Parsing...\n");
  1383.             
  1384.     if( findHeader( p, vp, line, 0 )==0 )    /* set-up header */
  1385.         return;
  1386.  
  1387.     if(debug)
  1388.         notify("Title found\n");
  1389.  
  1390.     if( SkipTOC( p, vp, 1 ) == 0 )
  1391.     {
  1392.         if( outTPrg!=NULL ) fclose( outTPrg );
  1393.         if( outTMes!=NULL ) fclose( outTMes );
  1394.         if( outPrg!=NULL )  fclose( outPrg );
  1395.         if( outMes!=NULL )  fclose( outMes );
  1396.         if( inP!=NULL )     fclose( inP );
  1397.         return;
  1398.     }
  1399.  
  1400.     if( DoMessages( p, vp, line )==0 )
  1401.     {
  1402.         if( outTPrg!=NULL ) fclose( outTPrg );
  1403.         if( outTMes!=NULL ) fclose( outTMes );
  1404.         if( outPrg!=NULL )  fclose( outPrg );
  1405.         if( outMes!=NULL )  fclose( outMes );
  1406.         if( inP!=NULL )     fclose( inP );
  1407.         return;
  1408.     }
  1409.     
  1410.     if(debug)
  1411.         notify("End of digest found...\n");
  1412.  
  1413.     if( outTPrg!=NULL ) 
  1414.     {
  1415.         WriteTrailer(outTPrg);
  1416.         fclose(outTPrg);
  1417.     }
  1418.     
  1419.     if( outTMes!=NULL ) 
  1420.     {
  1421.         WriteTrailer(outTMes);
  1422.         fclose(outTMes);
  1423.     }
  1424.     
  1425.     if( outPrg!=NULL ) 
  1426.     {
  1427.         WriteTrailer(outPrg);
  1428.         fclose(outPrg);
  1429.     }
  1430.     
  1431.     if( outMes!=NULL ) 
  1432.     {
  1433.         WriteTrailer(outMes);
  1434.         fclose(outMes);
  1435.     }
  1436.     
  1437.     notify("file closed.\n");
  1438.     
  1439. #ifdef __THINK__
  1440.     SetUpAllFinderInfo( p, vp );
  1441. #endif
  1442. }
  1443.  
  1444. int HandleArgs( ParsP p, int num_args, char *arg_strings[], char *digestName, char *parsName )
  1445. {
  1446.     int i;
  1447.     
  1448.     strcpy( parsName, "digester.par");
  1449.     
  1450.     if( num_args<2 )
  1451.     {
  1452.         notify("You can also start digester from the command line.\n");
  1453.         notify("%s <filename> <b> <2> <3> <p> <f=digest.par>\n", arg_strings[0]);
  1454.         notify("b: use fancy buttons and icons.\n");
  1455.         notify("2: split up file in 2 parts\n");
  1456.         notify("3: split up file in 3 parts\n");
  1457.         notify("p: enable post reply.\n");
  1458.         notify("f=: alternative parameters file.\n");
  1459.     }
  1460.     else
  1461.     {
  1462.         p->Type=1;
  1463.         p->Buttons=0;
  1464.         p->Mail=0;
  1465.         
  1466.         strcpy( digestName, arg_strings[1] );
  1467.         
  1468.         for(i=2; i<num_args; i++)
  1469.         {
  1470.             switch( (arg_strings[i])[0] )
  1471.             {
  1472.                 case 'b':
  1473.                     p->Buttons=1;
  1474.                     notify("Buttons on!\n");
  1475.                 break;
  1476.                 
  1477.                 case '3':
  1478.                     p->Type=2;
  1479.                     notify("Split into 3 files!\n");
  1480.                 break;
  1481.                 
  1482.                 case '2':
  1483.                     p->Type=3;
  1484.                     notify("Split into 2 files!\n");
  1485.                 break;
  1486.                 
  1487.                 case 'p':
  1488.                     p->Mail=1;
  1489.                     notify("Enable post reply.\n");
  1490.                 break;
  1491.  
  1492.                 case 'f':
  1493.                     if( ((arg_strings[i])[1]=='=') && (strlen(arg_strings[i])>2) )
  1494.                     {
  1495.                         strcpy( parsName, (arg_strings[i]+2) );
  1496.                     }
  1497.                 break;
  1498.  
  1499.                 default:
  1500.                     notify("Usage: %s <filename> <b> <2> <3> <p>\n", arg_strings[0]);
  1501.                     notify("b: use fancy buttons and icons.\n");
  1502.                     notify("2: split up file in 2 parts\n");
  1503.                     notify("3: split up file in 3 parts\n");
  1504.                     notify("p: enable post reply.\n");
  1505.                     return(0);
  1506.             }
  1507.         }
  1508.     }
  1509.     
  1510.     return(1);
  1511. }
  1512.  
  1513. int GetSites( ParsP p )
  1514. {
  1515.     char    line[256];
  1516.     FILE    *sitesP;
  1517.     int        i;
  1518.     
  1519.     notify("\nGetting file of sites...\n");
  1520.     
  1521.     if((sitesP=fopen(p->sitesFile,"r"))==NULL)
  1522.     {
  1523.         notify("Can't open file sites file.\n");
  1524.         return(0);
  1525.     }
  1526.     
  1527.     p->nSites=atoi(fgets( line, 256, sitesP));
  1528.     
  1529.     if((p->sites=malloc(p->nSites*LINELENGTH))==NULL)
  1530.     {
  1531.         notify("Out of memory error...\n");
  1532.         return(0);
  1533.     }
  1534.     
  1535.     for( i=0; i<p->nSites; i++ )
  1536.         fgets( i*LINELENGTH+p->sites, LINELENGTH, sitesP);
  1537.     
  1538.     fclose(sitesP);
  1539.     
  1540.     return(1);
  1541. }
  1542.  
  1543. void convertCodes( char *line )
  1544. {
  1545.     char     tempLine[256];
  1546.     int    l, i;
  1547.     
  1548.     tempLine[0]=0;
  1549.     l = 0;
  1550.     for(i=0; i<strlen(line); i++ )
  1551.     {
  1552.         if( line[i]=='\\' )
  1553.         {
  1554.             tempLine[l++] = line[i]-'a'+1;
  1555.             tempLine[l] = 0;
  1556.         }        
  1557.         else
  1558.         {
  1559.             tempLine[l++] = line[i];
  1560.             tempLine[l] = 0;
  1561.         }
  1562.     }
  1563.     strcpy( line, tempLine );
  1564. }
  1565.  
  1566. void checkPar( char *line, char *token, char *par, int max )
  1567. {
  1568.     char *bptr, *eptr;
  1569.     
  1570.     if( strncmp( line, token, strlen(token) )!=0 ) return;
  1571.     
  1572.     bptr = line+strlen(token);
  1573.     
  1574.     while( (*bptr!='"') && (*bptr!=0) ) bptr++;        /* find first quote */
  1575.     
  1576.     if(*bptr==0)
  1577.     {
  1578.         notify("Failed to read parameter value of '%s'\n", token);
  1579.         return;
  1580.     }
  1581.     
  1582.     eptr=bptr+1;
  1583.  
  1584.     while( (*eptr!='"') && (*eptr!=0) ) eptr++;        /* find second quote */
  1585.     
  1586.     if(*eptr==0)
  1587.     {
  1588.         notify("Failed to read parameter string of '%s'\n", token);
  1589.         return;
  1590.     }
  1591.     
  1592.     if((eptr-bptr)>max)
  1593.     {
  1594.         notify("Parameter string of '%s' too long\n", token);
  1595.         return;
  1596.     }
  1597.  
  1598.     *eptr=0;    /* terminate the string */
  1599.     
  1600.     strcpy( par, bptr+1 );    /* copy the parameter string */
  1601.     
  1602.     if( debug )
  1603.         notify( "Parameter '%s': %s\n", token, par );
  1604.         
  1605.     convertCodes( par );
  1606. }
  1607.  
  1608. void checkParNum( char *line, char *token, int *par )
  1609. {
  1610.     if( strncmp( line, token, strlen(token) )!=0 ) return;
  1611.  
  1612.     if( sscanf( line+strlen(token), "%d", par )!=1 )
  1613.         notify("Failed to get parameter '%s'.\n", token);    
  1614.     else
  1615.     if( debug )
  1616.         notify("Parameter '%s': %d\n", token, *par );
  1617. }
  1618.  
  1619. void InitPars( ParsP p )
  1620. {
  1621.     /* initialize all struct variables */
  1622.     
  1623.     strcpy( p->scriptPath,     "/vdham-bin/" );
  1624.     strcpy( p->sitesFile,     "sites.asc" );
  1625.     strcpy( p->destPath,     "" );
  1626.     strcpy( p->Ftype, "TEXT" );
  1627.     strcpy( p->Fcreator, "MOSS" );
  1628.  
  1629.     strcpy( p->DigestName,     "infomac.txt" );
  1630.     strcpy( p->nameAll,     "IM%d-%d.html" );
  1631.     strcpy( p->nameTOC,     "IMt%d-%d.html" );
  1632.     strcpy( p->nameProg,     "IMp%d-%d.html" );
  1633.     strcpy( p->nameMess,     "IMm%d-%d.html" );
  1634.     
  1635.     strcpy( p->BegOfDigest, "Info-Mac Digest      " );
  1636.     strcpy( p->Volume,         "Volume" );
  1637.     strcpy( p->Issue,         "Issue" );
  1638.     strcpy( p->Date,         "" );
  1639.     
  1640.     strcpy( p->EndOfDigest, "End of Info-Mac Digest" );
  1641.     strcpy( p->BeginOfTopics, "Today's Topics:" );
  1642.     strcpy( p->EndOfTopics, "----------------------------------------------------------------------" );
  1643.     strcpy( p->EndOfMessage, "------------------------------\n" );
  1644.     
  1645.     strcpy( p->RootPath,     "/info-mac/" );
  1646.     strcpy( p->BegOfFile,     "[Archived as " );
  1647.     strcpy( p->EndOfFile,     ";" );
  1648.     
  1649.     p->Type        = 1;
  1650.     p->Buttons    = 1;
  1651.     p->Mail     = 1;
  1652.     p->Files     = 1;
  1653.     p->URLs     = 1;
  1654.     p->MURLs     = 0;
  1655.  
  1656.     p->sites     = NULL;
  1657.     p->nSites     = 0;
  1658. }
  1659.  
  1660. int GetParameters( ParsP p, char *name, int *promptP )
  1661. {
  1662.     FILE     *inP;
  1663.     char    *cptr;
  1664.     char    line[256];
  1665.     
  1666.     notify("Using parameter file: '%s'.\n", name );
  1667.     
  1668.     if( (inP = fopen(name, "r")) == NULL )
  1669.     {
  1670.         notify("Cannot open '%s', using default values\n", name);
  1671.         return(1);
  1672.     }
  1673.     
  1674.     while( !feof(inP) )
  1675.     {
  1676.         fgets( line, 256, inP );
  1677.         
  1678.         if( (cptr=strstr(line, "#")) != NULL )    /* mask comments */
  1679.         {
  1680.             *cptr=0;
  1681.         }
  1682.         
  1683.         if(strlen(line)>2)
  1684.         {
  1685.             checkPar( line, "SCRIPT", p->scriptPath,80 );
  1686.             checkPar( line, "SITE", p->sitesFile,20 );
  1687.             checkPar( line, "PATH", p->destPath,80 );
  1688.             checkPar( line, "FTYPE", p->Ftype,6 );
  1689.             checkPar( line, "FCREAT", p->Fcreator, 6 );
  1690.     
  1691.             checkPar( line, "DIGNAM", p->DigestName,20);
  1692.             checkPar( line, "NAMA", p->nameAll,20);
  1693.             checkPar( line, "NAMT", p->nameTOC,20);
  1694.             checkPar( line, "NAMP", p->nameProg,20);
  1695.             checkPar( line, "NAMM", p->nameMess,20);
  1696.     
  1697.             checkPar( line, "BOD", p->BegOfDigest,80);
  1698.             checkPar( line, "VOL", p->Volume,80);
  1699.             checkPar( line, "ISS", p->Issue,80);
  1700.             checkPar( line, "DAT", p->Date,20);
  1701.     
  1702.             checkPar( line, "EOD", p->EndOfDigest,80);
  1703.             checkPar( line, "BOT", p->BeginOfTopics,80);
  1704.             checkPar( line, "EOT", p->EndOfTopics,80);
  1705.             checkPar( line, "EOM", p->EndOfMessage,80);
  1706.     
  1707.             checkPar( line, "RTD", p->RootPath,20);
  1708.             checkPar( line, "BOF", p->BegOfFile,40);
  1709.             checkPar( line, "EOF", p->EndOfFile,20);
  1710.     
  1711.             checkParNum( line, "TYP", &(p->Type));
  1712.             checkParNum( line, "BUT", &(p->Buttons));
  1713.             checkParNum( line, "MAI", &(p->Mail));
  1714.             checkParNum( line, "FIL", &(p->Files));
  1715.             checkParNum( line, "URL", &(p->URLs));
  1716.             checkParNum( line, "MURL", &(p->MURLs));
  1717.             checkParNum( line, "DEBUG", &debug);
  1718.             checkParNum( line, "PROMPT", promptP);
  1719.         }
  1720.     }
  1721.     return(0);
  1722. }
  1723.  
  1724. int main( int num_args, char *arg_strings[] )
  1725. {
  1726.     char    digestName[80], answer[80], parsName[80];
  1727.     char    line[256];
  1728.     struct Pars    p;
  1729.     int        nopars;
  1730.     int        prompt=1;
  1731.  
  1732.     InitPars( &p );
  1733.     
  1734.     if( HandleArgs( &p, num_args, arg_strings, digestName, parsName )==0 )
  1735.         return(1);
  1736.  
  1737.     nopars=GetParameters( &p, parsName, &prompt );
  1738.  
  1739.     if( p.Files )
  1740.     {
  1741.         if( GetSites( &p )==0 )
  1742.             return(1);
  1743.     }
  1744.  
  1745.  
  1746.     notify("\n\n*** D I G E S T E R ***\n\n");
  1747.     notify("by Andre' C. van der Ham\n\n");
  1748.     notify("This program parses info-mac digests you get by e-mail.\n");
  1749.     notify("Save the e-mail without headers and paragraph recognition (Eudora)\n");
  1750.     notify("Please, use one digest per file.\n");
  1751.     notify("Convert file to appropriate ascii format, for example: Mac->Unix\n\n");
  1752.     notify("The file can contain a number of digests.\n");
  1753.     notify("An HTML file is generated for each issue.\n");
  1754.     notify("Send bug reports, questions, etc... to:\n");
  1755.     notify("e-mail: A.C.vanderHam@ET.TUDelft.NL\n\n\n");
  1756.  
  1757.     if( num_args<2 )
  1758.     { 
  1759. #ifndef __THINK__
  1760.  
  1761.         notify("Input file (%s): ", p.DigestName);        
  1762.         gets( digestName );
  1763.         if(strlen(digestName)<2)
  1764.             strcpy( digestName, p.DigestName);
  1765. #else
  1766.         if( GetName( digestName )==0 ) return(1);
  1767. #endif
  1768.  
  1769.         if(prompt)
  1770.         {
  1771.             notify("Use fancy buttons and icons (y/N): ");
  1772.             gets( answer );
  1773.         
  1774.             if( answer[0]=='y' )
  1775.                 p.Buttons=1;
  1776.             else
  1777.                 p.Buttons=0;
  1778.         
  1779.             notify("Include message selection button for reply (y/N): ");
  1780.             gets( answer );
  1781.         
  1782.             if( answer[0]=='y' )
  1783.                 p.Mail=1;
  1784.             else
  1785.                 p.Mail=0;
  1786.         
  1787.             notify("Split file into 3 separate files for topics, programs and messages (y/N): ");
  1788.             gets( answer );
  1789.         
  1790.             if( answer[0]=='y' ) 
  1791.                 p.Type=2;
  1792.             else
  1793.                 p.Type=1;
  1794.     
  1795.             notify("Split file into 2 separate files for programs and messages (y/N): ");
  1796.             gets( answer );
  1797.         
  1798.             if( answer[0]=='y' ) 
  1799.                 p.Type=3;
  1800.         }
  1801.     }
  1802.  
  1803.     ParseOne( &p, digestName );
  1804.     
  1805.     notify("Thanks for using Digester.\nHave a nice day.\n");
  1806. #ifdef __THINK__
  1807.     notify("Please press Return to continue.\n");
  1808. #endif
  1809.  
  1810.     return(0);
  1811. }